package com.yihusitian.zsxq.sg.generator;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.google.common.collect.Sets;
import com.yihusitian.zsxq.sg.clazz.DynamicLoader;
import com.yihusitian.zsxq.sg.config.BaseClassInfo;
import com.yihusitian.zsxq.sg.config.DOInfo;
import com.yihusitian.zsxq.sg.entity.FieldInfo;
import com.yihusitian.zsxq.sg.util.CommonInfoHolder;
import com.yihusitian.zsxq.sg.config.BaseClassInfo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.ObjectStreamClass;
import java.util.List;
import java.util.Set;

/**
 * @Description 模型对象生成器
 * @Author LeeHo
 * @Date 2020/8/26 10:21
 */
@Slf4j
public class DOSourceGenerator implements SourceGenerator {

    @Getter
    protected Set<String> importSet = Sets.newHashSet();

    @Override
    public BaseClassInfo getBaseClassInfo() {
        return generateConfigHolder.getDoInfo();
    }

    private final String PK_VAL_CONTENT_TEMPLATE = "@Override\n" +
            "    protected Serializable pkVal() {\n" +
            "        return %s;\n" +
            "    }";

    @Override
    public String getMainContent() {
        List<FieldInfo> fieldInfoList = CommonInfoHolder.getCurrentFieldInfoList();
        StringBuilder content = new StringBuilder();
        String innerClassName = CommonInfoHolder.getCurrentBusinessName() + "Column";
        String idProperty = null;
        for (FieldInfo fieldInfo : fieldInfoList) {
            content.append(TAB_NEW_LINE);
            content.append(NOTE).append(fieldInfo.getComment()).append(TAB_NEW_LINE);
            if (fieldInfo.isPrimaryId()) {
                idProperty = fieldInfo.getPropertyName();
                content.append(String.format("@TableId(value = %s.%s%s)", innerClassName, fieldInfo.getColumnField().toUpperCase(), fieldInfo.isPrimaryIdAutoIncrement() ? ", type = IdType.AUTO" : StringUtils.EMPTY)).append(TAB_NEW_LINE);
                if (fieldInfo.isPrimaryIdAutoIncrement()) {
                    this.importSet.add("import com.baomidou.mybatisplus.annotation.IdType;");
                }
            } else {
                content.append(String.format("@TableField(value = %s.%s, insertStrategy = FieldStrategy.NOT_NULL, updateStrategy = FieldStrategy.NOT_NULL)", innerClassName, fieldInfo.getColumnField().toUpperCase())).append(TAB_NEW_LINE);
            }
            String importLine = this.getImportLine(fieldInfo);
            if (StringUtils.isNotEmpty(importLine)) {
                this.importSet.add(importLine);
            }
            content.append(String.format("private %s %s;", fieldInfo.getJavaType(), fieldInfo.getPropertyName())).append(TAB_NEW_LINE);
        }
        content.append(TAB_NEW_LINE).append(String.format(PK_VAL_CONTENT_TEMPLATE, idProperty)).append(TAB_NEW_LINE);
        // 添加内部枚举类
        content.append(TAB_NEW_LINE).append(this.getInnerClassContent(innerClassName));
        return content.toString();
    }

    /**
     * 获取导入信息
     *
     * @param fieldInfo
     * @return
     */
    protected String getImportLine(FieldInfo fieldInfo) {
        String result = StringUtils.EMPTY;
        if (fieldInfo.getJavaType().equals("Date")) {
            result = "import java.util.Date;";
        }
        if (fieldInfo.getJavaType().equals("BigDecimal")) {
            result = "import java.math.BigDecimal;";
        }
        return result;
    }

    /**
     * 获取内部类的内容
     *
     * @param innerClassName
     * @return
     */
    private String getInnerClassContent(String innerClassName) {
        List<FieldInfo> fieldInfoList = CommonInfoHolder.getCurrentFieldInfoList();
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(String.format("public class %s{", innerClassName)).append(TAB_NEW_LINE);
        fieldInfoList.forEach(item -> {
            stringBuilder.append(TAB).append(String.format("public static final String %s = \"%s\";", item.getColumnField().toUpperCase(), item.getColumnField())).append(TAB_NEW_LINE);
        });
        stringBuilder.append("}");
        return stringBuilder.toString();
    }

    /**
     * 获取SerialVersionUID
     *
     * @param sourceContent
     * @param packagePath
     * @param fileName
     * @return
     */
    @Override
    public String getSerialVersionUIDLine(String sourceContent, String packagePath, String fileName) {
        if (getBaseClassInfo() instanceof DOInfo) {
            return generateSerialVersionUIDLine(sourceContent, packagePath, fileName);
        }
        return StringUtils.EMPTY;
    }

    /**
     * 生成SerialVersionUID
     *
     * @param sourceContent
     * @param packagePath
     * @param fileName
     * @return
     */
    private String generateSerialVersionUIDLine(String sourceContent, String packagePath, String fileName) {
        try(DynamicLoader.MemoryClassLoader classLoader = new DynamicLoader.MemoryClassLoader(DynamicLoader.compile(fileName, sourceContent))) {
            //如果出现ClassNotFoundExceptionH:com.sun.tools.javac.processing.JavacProcessingEnvironment
            //请先在当前项目的ClassPath路径下添加tools.jar, 详情请看:https://blog.csdn.net/qq_39514033/article/details/103999277
            Class clazz = classLoader.loadClass(packagePath + StrUtil.DOT + fileName.replace(StringPool.DOT_JAVA, StringUtils.EMPTY));
            ObjectStreamClass c = ObjectStreamClass.lookup(clazz);
            long serialVersionUID = c.getSerialVersionUID();
            log.info("为{}生成serialVersionUID:{}", fileName, serialVersionUID);
            return String.format(TAB_NEW_LINE + "private static final long serialVersionUID = %sL;", serialVersionUID);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return StringUtils.EMPTY;
    }
}